﻿using System;
using System.Collections.Generic;
using System.Linq;
using Domain;

namespace Presentation
{
    public class Presenter
    {
        private IView view;
        private readonly List<ILog> loggers = new List<ILog>();
        static public Converter Converter = new Converter();

        private void WriteLog(string message)
        {
            foreach (var logger in loggers)
            {
                logger.Log = message;
            }
        }

        public void AddLogger(ILog logger)
        {
            if (!loggers.Contains(logger))
                loggers.Add(logger);
        }

        private void RemoveLogger(ILog logger)
        {
            if (loggers.Contains(logger))
                loggers.Remove(logger);
        }

        public Presenter(IView view)
        {
            Rebind(view);
            this.view.Quotations = Converter.GetQuotations();
            InitCurrencyList();
        }

        public void Rebind(IView v)
        {
            v.OnConvertClick += ConvertClick;
            v.OnSaveQuotationsClick += SaveQuotationsClick;
            v.OnAddCurrencyClick += AddCurrencyClick;
            v.OnLogCheckedChanged += EnableLogger;
            view = v;
            view.Quotations = Converter.GetQuotations();
        }

        private void InitCurrencyList()
        {
            var list = view.Quotations.Select(pair => pair.Key).ToList();
            var arr = new string[list.Count];
            list.CopyTo(arr,0);
            view.Currencies = arr;
        }

        private bool CheckConvertInputs()
        {
            double d;
            var res = Double.TryParse(view.FromValue, out d);

            if (!res)
            {
                view.ErrorMessage = ErrorMessage.IncorrectConvertInput;
                WriteLog("Конвертирование: " + ErrorMessage.IncorrectConvertInput + " " + view.FromValue);
                return false;
            }

            return true;
        }

        private bool CheckSaveQuotationsInputs()
        {
            foreach (var pair in view.Quotations)
            {
                double d;
                var res = Double.TryParse(pair.Value, out d);

                if (res) continue;

                view.ErrorMessage = ErrorMessage.IncorrectQuotationInput;
                WriteLog("Сохранение котировок: " + ErrorMessage.IncorrectQuotationInput + " " + pair.Value.ToString());
                return false;
            }

            return true;
        }

        private bool CheckAddCurrencyInputs()
        {
            double d;
            var res = Double.TryParse(view.NewValue, out d);

            if (!res)
            {
                view.ErrorMessage = ErrorMessage.IncorrectNewCurrencyInput;
                WriteLog("Добавление новой валюты: " + ErrorMessage.IncorrectNewCurrencyInput + " " + view.NewValue);
                return false;
            }

            if (view.NewName.Trim().Length == 0)
            {
                view.ErrorMessage = ErrorMessage.EmptyNewCurrencyName;
                WriteLog("Добавление новой валюты: " + ErrorMessage.EmptyNewCurrencyName);
                return false;
            }

            return true;
        }

        private void ConvertClick()
        {
            view.ClearError();
            view.ToValue = "-";

            if (!CheckConvertInputs()) return;

            try
            {
                view.Quotations = Converter.GetQuotations();
                var result = Converter.ConvertCurrency(view.FromName, view.ToName, Convert.ToDouble(view.FromValue));
                WriteLog("Конвертирование: из " + view.FromValue + " " + view.FromName + " в " + view.ToName);

                view.ToValue = result.ToString();
                WriteLog("Конвертирование: результат = " + result);
            }
            catch (NegativeCountException)
            {
                view.ErrorMessage = ErrorMessage.NegativeValueForConvert;
                WriteLog("Конвертирование: " + ErrorMessage.NegativeValueForConvert + " " + view.FromValue);
            }
            catch (NotContainException)
            {
                view.ErrorMessage = ErrorMessage.CurrencyNotExist;
                WriteLog("Конвертирование: " + ErrorMessage.CurrencyNotExist + " " + view.FromName);
            }
        }

        private void SaveQuotationsClick()
        {
            view.ClearError();

            if (!CheckSaveQuotationsInputs()) return;

            var newQuptations = view.Quotations.ToDictionary(pair => pair.Key, pair => Convert.ToDouble(pair.Value));

            try
            {
                Converter.UpdateQuotations(newQuptations);
                WriteLog("Сохранение котировок: сохранение новых котировок");
            }
            catch (NegativeCountException)
            {
                view.ErrorMessage = ErrorMessage.NegativeValueForQuotation;
                WriteLog("Сохранение котировок: " + ErrorMessage.NegativeValueForQuotation + " " + view.FromValue);
            }

            view.Quotations = Converter.GetQuotations();
            InitCurrencyList();
        }

        private void AddCurrencyClick()
        {
             view.ClearError();

             if (!CheckAddCurrencyInputs()) return;

             var name = view.NewName;
             var value = Convert.ToDouble(view.NewValue);

             try
             {
                 Converter.AddCurrency(name, value);
                 view.Quotations = Converter.GetQuotations();
                 InitCurrencyList();
                 WriteLog("Добавление новой валюты: добавление новой валюты " + name + " с котировкой " + value.ToString());
             }
             catch (AlreadyContainException)
             {
                 view.ErrorMessage = ErrorMessage.CurrencyAlreadyExist;
                 WriteLog("Добавление новой валюты: " + ErrorMessage.CurrencyAlreadyExist + " " + name);
             }
             catch (NegativeCountException)
             {
                 view.ErrorMessage = ErrorMessage.NegativeValueForQuotation;
                 WriteLog("Добавление новой валюты: " + ErrorMessage.NegativeValueForQuotation + " " + value.ToString());
             }
        }

        private void EnableLogger(ILog logger, bool enable)
        {
            if (enable)
            {
                AddLogger(logger);
            }
            else
            {
                RemoveLogger(logger);
            }
        }
    }
}
